#!/usr/bin/env python
import os
from functools import partial
import threading
import rclpy
from rclpy.executors import ExternalShutdownException
import json
import requests
import sys
from semantic_nav.socket_utils import SocketServer
from semantic_nav.action_utils import PriorQueClient
from semantic_nav_interfaces.action import NavStr
from semantic_nav.log_utils import get_logger
logger = get_logger()
PROCESS_RATE = 0.4


def return_to_ui(ctx, response, meadow_ip_port):
    if len(response) < 1:
        return
    headers = {
        'Content-Type': 'application/json',
        'Authorization': ctx.get('auth'),
    }
    # logger.info(headers)
    data = {
        'session': ctx.get('session'),
        'member': int(ctx.get('member')),  # Attention! It's int, not str!
        'text': response,
    }
    # logger.info(data)
    resp = requests.post(
        url=f'http://{meadow_ip_port}/api/dialog/',  # Meadow's web endpoint; the IP and port might change
        headers=headers,
        data=json.dumps(data)
    )

    # logger.info(resp.text)
    if resp.status_code == 201:
        logger.info('Return to ui: success')
    else:
        logger.info('Return to ui: failed')


def main(args=None):
    rclpy.init(args=args)
    socket_ip = os.getenv('NAV_SOCKET_IP', '0.0.0.0')
    socket_port = int(os.getenv('NAV_SOCKET_PORT', '10086'))
    logger.info(f"Server started, listening on {socket_ip}:{socket_port}")
    return_to_meadow_ui = partial(return_to_ui, meadow_ip_port=os.getenv('MEADOW_IP_PORT', '127.0.0.1:8080'))
    nav_client = PriorQueClient(action_type=NavStr, action_name="semantic_nav")
    spin_thread = threading.Thread(target=rclpy.spin, args=[nav_client])
    try:
        server = SocketServer(socket_ip, socket_port)
        server.start()
        logger.info("Server started")
        rate = nav_client.create_rate(10.0)
        spin_thread.start()
        while rclpy.ok():
            if server.accept_client():
                message = server.recv()
                if message is not None:
                    ctx = json.loads(message)
                    nav_client.execute_succeeded = lambda result: return_to_meadow_ui(ctx, result.result)
                    nav_client.execute_feedback = lambda feedback: return_to_meadow_ui(ctx, feedback.feedback)
                    goal = NavStr.Goal()
                    goal.priority = goal.LOW_PRIORITY
                    # goal.type = goal.TYPE_QA
                    goal.input = ctx.get('input_text')
                    nav_client.invoke([goal])
                    message = None
            rate.sleep()
    except KeyboardInterrupt:
        pass
    except ExternalShutdownException:
        sys.exit(1)
    finally:
        nav_client.destroy_node()


if __name__ == '__main__':
    main()
